<template>
    <div class="app-container encode-setting">
        <!-- 全局配置 -->
        <el-card :header="$t('overall_config')">
            <div>
                <!-- 视频-title -->
                <el-row :gutter="24">
                    <el-col :md="3" :sm="6"></el-col>
                    <el-col :md="12" :sm="16">
                        <el-row :gutter="24">
                            <el-col :sm="6">{{ $t('video size') }}</el-col>
                            <el-col :sm="12">{{ $t('codec') }}</el-col>
                            <el-col :sm="6">{{ $t('rate control') }}</el-col>
                        </el-row>
                    </el-col>
                    <el-col :md="3" :sm="4">{{ $t('bitrate') }}(kb/s)</el-col>
                    <el-col :md="3" :sm="4">{{ $t('framerate') }}</el-col>
                    <el-col :md="3" :sm="4">GOP({{ $t('second') }})</el-col>
                </el-row>
                <!-- 主流 -->
                <video-stream type="all" :name="$t('main_stream')" :data="all" :videoSizeOptions="videoSizeOptions"
                    :codecOptions="codecOptions" :rcmodeOptions="rcmodeOptions"></video-stream>
                <!-- 辅流 -->
                <video-stream type="all" :name="$t('sub_stream')" :data="all_sub" :videoSizeOptions="videoSizeOptions"
                    :codecOptions="codecOptions" :rcmodeOptions="rcmodeOptions"></video-stream>

                <el-divider></el-divider>
                <!-- 音频参数-title -->
                <el-row :gutter="24">
                    <el-col :md="3" :sm="6"></el-col>
                    <el-col :sm="4">{{ $t('codec') }}</el-col>
                    <el-col :sm="4">{{ $t('source') }}</el-col>
                    <el-col :sm="4">{{ $t('gain') }}</el-col>
                    <el-col :sm="3">{{ $t('samplerate') }}</el-col>
                    <el-col :md="3" :sm="4">{{ $t('channels') }}</el-col>
                    <el-col :md="3" :sm="4">{{ $t('bitrate') }}(kb/s)</el-col>
                </el-row>
                <!-- 音频参数 -->
                <audio-stream :name="$t('Audio config')" :data="allAudio" :audioSourceOptions="audioSourceOptions"
                    :audioCodecOptions="audioCodecOptions" :gainOptions="gainOptions"
                    :samplerateOptions="samplerateOptions"></audio-stream>

                <div class="btns">
                    <el-button type="primary" size="large" @click="setAll">{{ $t('Save to local') }}</el-button>
                    <el-button type="primary" size="large" @click="setGroup">{{ $t('Save to group') }}</el-button>
                </div>
            </div>

        </el-card>

        <el-tabs v-model="activeName" type="border-card" style="margin-top:40px;position: relative;min-height: 300px;">
            <el-tab-pane :label="$t('Encode config')" name="tab_hdmi">
                <tab-hdmi-tmp type="tab_hdmi" :data="tab_hdmi_data" :videoSizeOptions="videoSizeOptions"
                    :codecOptions="codecOptions" :rcmodeOptions="rcmodeOptions"></tab-hdmi-tmp>
            </el-tab-pane>
            <el-tab-pane :label="$t('Advanced Encode config')" name="tab_adv">
                <tab-adv-tmp :data="tab_hdmi_data" :hardware="hardware"></tab-adv-tmp>
            </el-tab-pane>
            <el-tab-pane :label="$t('Video config')" name="tab_video"
                v-if="hardware.chip != '3559A' && hardware.chip != '3516E'">
                <tab-video-tmp :data="[...tab_video_data, ...tab_videoNet_data]"></tab-video-tmp>
            </el-tab-pane>
            <el-tab-pane :label="$t('Audio config')" name="tab_audio">
                <tab-audio-tmp :data="tab_audio_data" :audioSourceOptions="audioSourceOptions"
                    :audioCodecOptions="audioCodecOptions" :gainOptions="gainOptions"
                    :samplerateOptions="samplerateOptions"></tab-audio-tmp>
            </el-tab-pane>
            <el-tab-pane :label="$t('Network stream')" name="tab_net" v-if="showTabNet">
                <tab-net-tmp :data="tab_net_data"></tab-net-tmp>
            </el-tab-pane>
        </el-tabs>

        <div class="btns">
            <el-button type="primary" size="large" @click="save">{{ $t('Save') }}</el-button>
        </div>
        <!-- 群组同步 -->
        <GroupList ref="GroupListRef" @groupSync="groupSync"></GroupList>
    </div>
</template>
  
<script setup name="encode-setting">
import { ElMessageBox, ElDialog } from 'element-plus'
import modal from "@/plugins/modal.js"
import videoStream from "./components/videoStream.vue"
import audioStream from "./components/audioStream.vue"
import tabHdmiTmp from "./components/tabHdmiTmp.vue"
import tabAdvTmp from "./components/tabAdvTmp.vue"
import tabVideoTmp from "./components/tabVideoTmp.vue"
import tabAudioTmp from "./components/tabAudioTmp.vue"
import tabNetTmp from "./components/tabNetTmp.vue"
import GroupList from '@/components/GroupList/index.vue'
import RPC from "@/api/rpc"
import getJson from "@/api/getJson"
import i18n from '@/lang'
import { cloneDeep } from 'lodash'
import { nextTick } from 'vue'

// modal.loading('Loading...')

let hardware = reactive({})
let config = reactive([]) 

let hasInitOption = ref(false)

function handleInit(type) {
    // console.log('开始handleInit')
    config.length = 0
    let p1 = getJson('/config/hardware.json')
    let p2 = getJson('/config/config.json')

    Promise.all([p1, p2]).then(res => {
        let [r1, r2] = res
        hardware = Object.assign(hardware, r1.data)
        config = config.concat(r2.data)
        // console.log('handleInit config =========== ', config)
        init(type)

        if (!hasInitOption.value) {
            initOptions()
        }
    }).finally(() => {
        nextTick(() => {
            // modal.closeLoading()
        })
    })
}
handleInit('load')


let all = reactive({})
let allAudio = reactive({})
let all_sub = reactive({})

let tab_hdmi_data = reactive([]);       // tab1 tab2
let tab_video_data = reactive([]);      // tab3
let tab_videoNet_data = reactive([]);   // tab3
let tab_audio_data = reactive([]);      // tab4
let tab_net_data = reactive([]);        // tab5

let activeName = ref('tab_hdmi')

let showTabNet = ref(true)

let audioSourceOptions = ref([
    { value: "source", label: "Default" },
])

function init(type) {
    // 分发tab数据
    setTabData()

    // 全局配置-主流
    let obj1 = cloneDeep(tab_hdmi_data[0].encv)
    Object.assign(all, {
        ...obj1,
        'width_height': obj1.width + 'x' + obj1.height,
        'codec_profile': obj1.codec + ',' + obj1.profile,
    })
    // 全局配置-辅流
    let obj2 = cloneDeep(tab_hdmi_data[0].encv2)
    Object.assign(all_sub, {
        ...obj2,
        'width_height': obj2.width + 'x' + obj2.height,
        'codec_profile': obj2.codec + ',' + obj2.profile,
    })
    // 全局配置-音频
    let obj3 = cloneDeep(tab_audio_data[0].enca)
    Object.assign(allAudio, obj3, { audioSrc: allAudio.audioSrc })
    if (type == "load") { allAudio.audioSrc = "source"; }

    nextTick(() => {
        // modal.closeLoading()
    })
}
function setTabData() {

    tab_hdmi_data.length = 0       // tab1 tab2
    tab_video_data.length = 0      // tab3
    tab_videoNet_data.length = 0   // tab3
    tab_audio_data.length = 0      // tab4
    tab_net_data.length = 0        // tab5

    audioSourceOptions.value = [{ value: "source", label: "Default" }]

    if (hardware.function.line) {
        audioSourceOptions.value.push({ value: "line", label: "Line" })
    }

    config.forEach(conf => {

        if (conf.enca != undefined) {
            audioSourceOptions.value.push({ value: conf.id, label: conf.name })
        }

        if (conf.enca?.audioSrc == "hdmi" || conf.enca?.audioSrc == "sdi") {
            conf.enca.audioSrc = conf.id;
        }

        // 分发数据
        if (conf.type == "net") {
            tab_net_data.push(conf);
            if (conf.net.decodeV) {
                tab_hdmi_data.push(conf);
            }
            if (conf.enable) {
                tab_audio_data.push(conf);
            }
        } else {
            if (conf.encv != undefined) {
                tab_hdmi_data.push(conf);
            }
            if (conf.enca != undefined) {
                tab_audio_data.push(conf);
            }
        }
        if (conf.type == "vi") {
            tab_video_data.push(conf);
        }

        if (conf.type == "net") {
            if (!conf.hasOwnProperty("cap")) {
                conf.cap = {
                    rotate: 0,
                    crop: {
                        B: 0,
                        L: 0,
                        R: 0,
                        T: 0
                    }
                }
            }
            tab_videoNet_data.push(conf);
        }

    })

    if (tab_net_data.length == 0) {
        showTabNet.value = false
    }

    // console.log('tab_hdmi_data =============', tab_hdmi_data)
    // console.log('tab_video_data =============', tab_video_data)
    // console.log('tab_videoNet_data =============', tab_videoNet_data)
    // console.log('tab_audio_data =============', tab_audio_data)
    // console.log('tab_net_data =============', tab_net_data)

}


function setAll() {

    let all_tmp = fmt(cloneDeep(all))
    let all_sub_tmp = fmt(cloneDeep(all_sub))
    let all_audio_tmp = cloneDeep(toRaw(allAudio))

    config.forEach(conf => {
        if (conf.encv == undefined || conf.enca == undefined) {
            return
        }
        Object.assign(conf.encv, all_tmp)
        Object.assign(conf.encv2, all_sub_tmp)
        Object.assign(conf.enca, all_audio_tmp, { audioSrc: all_audio_tmp.audioSrc == "source" ? conf.id : all_audio_tmp.audioSrc })
    })

    console.log('setAll ============ ', config)
    // setTabData()
    nextTick(() => {
        save()
    })

}
function fmt(obj) {
    obj.width = obj.width_height.split('x')[0]
    obj.height = obj.width_height.split('x')[1]
    delete obj.width_height
    obj.codec = obj.codec_profile.split(',')[0]
    obj.profile = obj.codec_profile.split(',')[1]
    delete obj.codec_profile
    return obj
}

function save() {
    let sum = 0;
    let maxENC = hardware.capability.encode.maxPixel
    config.forEach(conf => {
        if (conf.enable && conf.encv != undefined) {
            if (conf.encv.codec != "close")
                sum += conf.encv.width * conf.encv.height * conf.encv.framerate;
            if (conf.enable2 && conf.encv2.codec != "close") {
                sum += conf.encv2.width * conf.encv2.height * conf.encv2.framerate;
            }
        }
    })
    if (maxENC > 0 && sum > maxENC) {
        ElMessageBox.confirm(
            i18n.global.t('encodeSaveWarning'),
            i18n.global.t('Warning'),
            {
                confirmButtonText: i18n.global.t('I know'),
                type: 'warning',
                showCancelButton: false
            },
        )
        return
    }
    console.log('save ======= ', config)
    RPC("enc.update", [JSON.stringify(config, null, 2)]).then(res => {
        console.log('enc.update  =====  ', res)
        modal.msgSuccess(i18n.global.t('Save success'))
        nextTick(() => {
            handleInit();
        })
    }).catch(() => {
        modal.msgError(i18n.global.t('Save failed'))
    })
}

// 同步群组
const GroupListRef = ref()
function setGroup() {
    GroupListRef.value.open()
}
function groupSync(groupList) {
    let all_tmp = fmt(cloneDeep(all))
    let all_sub_tmp = fmt(cloneDeep(all_sub))
    let all_audio_tmp = cloneDeep(toRaw(allAudio))

    let obj = {
        encv: all_tmp,
        encv2: all_sub_tmp,
        enca: all_audio_tmp,
    }
    let proArr = []
    if (groupList.length > 0) {
        groupList.forEach(item => {
            item.status = 'pending'
            proArr.push(RPC("group.callSetEncode", [item.mac, obj]))
        })
    }
    Promise.all(proArr).then(res => {
        if (res.length > 0) {
            res.forEach((r, index) => {
                groupList[index].status = r.data.result ? 'success' : 'error'
            })
        }
        handleInit();
    })
}

let videoSizeOptions = ref([])
let codecOptions = ref([])
let rcmodeOptions = ref([])
let audioCodecOptions = ref([])
let gainOptions = ref([])
let samplerateOptions = ref([])

function initOptions() {

    hasInitOption.value = true

    videoSizeOptions.length = 0
    codecOptions.length = 0
    rcmodeOptions.length = 0
    audioCodecOptions.length = 0
    gainOptions.length = 0
    samplerateOptions.length = 0

    videoSizeOptions.value = [
        { value: '-1x-1', label: 'auto' },
        { value: '3840x2160', label: '4K', disabled: hardware.capability.encode.maxSize != '4K' },
        { value: '1920x1080', label: '1080p' },
        { value: '1280x720', label: '720p' },
        { value: '640x360', label: '360p' },
        { value: '1080x1920', label: '1080x1920' },
        { value: '720x1280', label: '720x1280' },
        { value: '360x640', label: '360x640' },
    ]
    codecOptions.value = [
        { value: 'h264,base', label: 'H.264 Baseline Profile' },
        { value: 'h264,main', label: 'H.264 Main Profile' },
        { value: 'h264,high', label: 'H.264 High Profile' },
        { value: 'h265,main', label: 'H.265 Main Profile' },
        { value: 'close,base', label: i18n.global.t('close') },
    ]
    rcmodeOptions.value = [
        { value: 'cbr', label: 'CBR' },
        { value: 'vbr', label: 'VBR' },
        { value: 'avbr', label: 'AVBR' },
        { value: 'fixqp', label: 'FIXQP' }
    ]
    audioCodecOptions.value = [
        { value: 'aac', label: 'AAC' },
        { value: 'pcma', label: 'PCMA' },
        { value: 'mp2', label: 'MPEG2' },
        { value: 'mp3', label: 'MP3' },
        { value: 'close', label: i18n.global.t('close') },
    ]
    gainOptions.value = [
        { value: 24, label: '+24dB' },
        { value: 18, label: '+18dB' },
        { value: 12, label: '+12dB' },
        { value: 6, label: '+6dB' },
        { value: 0, label: '+0dB' },
        { value: -6, label: '-24dB' },
        { value: -12, label: '-24dB' },
        { value: -18, label: '-24dB' },
        { value: -24, label: '-24dB' },
    ]
    samplerateOptions.value = [
        { value: -1, label: 'auto' },
        { value: 16000, label: '16K' },
        { value: 32000, label: '32K' },
        { value: 44100, label: '44.1K' },
        { value: 48000, label: '48K' },

    ]

}

</script>
  
<style scoped lang="scss">
.encode-setting {
    .btns {
        text-align: center;
        margin-top: 20px;
    }
}
</style>
  
  